home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / x2ftp / msdos / utils / ved04b / ved04b.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1994-12-15  |  38.2 KB  |  1,488 lines

  1. //--------------------------------------------------------------------------
  2. // filename "VED04B.CPP"
  3. // VED v0.4 beta
  4. // Vector Editor
  5. // coded by Tumblin / Bodies In Motion
  6. //--------------------------------------------------------------------------
  7.  
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <ctype.h>
  11. #include <alloc.h>
  12. #include <math.h>
  13. #include <conio.h>
  14. #include <dos.h>
  15. #include <XLib_all.h>
  16. #include "ved04clr.h"
  17.  
  18.  
  19. typedef long Fixedpoint;
  20.  
  21. #define Int2Fixed(a)    (Fixedpoint)((Fixedpoint)(a) << 16)
  22. #define Fixed2Int(a)    (int)((a) >> 16)
  23. #define Float2Fixed(a)    ((Fixedpoint)((a) * 65536.0))
  24. #define Fixed2Float(a)    ((a) / 65536.0)
  25.  
  26.  
  27. extern "C" {
  28.                          Fixedpoint FixedMul(Fixedpoint,Fixedpoint);
  29.                          Fixedpoint FixedDiv(Fixedpoint,Fixedpoint);
  30.                      };
  31.  
  32. //--------------------------------------------------------------------
  33.  
  34.  
  35. int debug_mode=0;    // 1=on, 0=off
  36.  
  37. #define MaxDegrees 360
  38.  
  39. #define WINDOW_TOP 0
  40. #define WINDOW_BOTTOM 239
  41. #define WINDOW_LEFT 0
  42. #define WINDOW_RIGHT 319
  43.  
  44.  
  45. int distance=256;    // distance of object from screen
  46.  
  47. // sin and cos lookup tables
  48. Fixedpoint cosine[MaxDegrees];
  49. Fixedpoint sine[MaxDegrees];
  50.  
  51. int xangle=0;
  52. int yangle=0;
  53. int zangle=0;
  54.  
  55. char filename[80];
  56.  
  57. unsigned int NumOfFrames=0;
  58.  
  59. float dotproduct;
  60.  
  61. int LightSourceMode=0;    // use default light source coordinates
  62.  
  63. unsigned char oldpalette[768];    // palette before running VED
  64. unsigned char currentpalette[768]={0};    // temporary palette for fading
  65.  
  66.  
  67. //--------------------------------------------------------------------
  68.  
  69.  
  70. // structure for one vertex
  71. typedef struct
  72. {
  73.     Fixedpoint ox;    // vertex's original coordinates
  74.     Fixedpoint oy;
  75.     Fixedpoint oz;
  76.     Fixedpoint wx;    // vertex's working coordinates
  77.     Fixedpoint wy;
  78.     Fixedpoint wz;
  79.     int sx;    // vertex's screen coordinates
  80.     int sy;
  81.     int sz;
  82. } VertexTYPE;
  83.  
  84.  
  85. // structure for polygons
  86. typedef struct
  87. {
  88.     int NumOfVertices;    // number of vertices in polygon
  89.     int Color;    // calculated color of the polygon
  90.     int ShadingColor;    // original VED v0.3 beta color for polygon (1-7)
  91.     int zmax,zmin;    // minimum and maximum
  92.     int xmax,xmin;    // minimum and maximum
  93.     int ymax,ymin;    // minimum and maximum
  94.     int zcenter;    // polygon's center in the z dimention
  95.     int xcenter;    // polygon's center in the x dimention
  96.     int ycenter;    // polygon's center in the y dimention
  97.     VertexTYPE **Vertex;    // array of pointers to vertices
  98.     Fixedpoint Normalox;    // original x coordinate of polygon normal
  99.     Fixedpoint Normaloy;    // original y coordinate of polygon normal
  100.     Fixedpoint Normaloz;    // original z coordinate of polygon normal
  101.     Fixedpoint Normalwx;    // working copy x coordinate of polygon normal
  102.     Fixedpoint Normalwy;    // working copy y coordinate of polygon normal
  103.     Fixedpoint Normalwz;    // working copy z coordinate of polygon normal
  104. } PolygonTYPE;
  105.  
  106.  
  107. // structure for vertex information of clipped polygons
  108. typedef struct
  109. {
  110.     int x,y,z;    // screen coordinates for clipped polygon vertices
  111.     int x1,y1,z1;    // intermediate coordinates (same as above)
  112. } ClipTYPE;
  113.  
  114.  
  115. // structure for clipped polygons
  116. typedef struct
  117. {
  118.     int NumOfVertices;    // # of vertices in clipped polygon
  119.     int Color;    // color of clipped polygon
  120.     ClipTYPE Vertex[50];    // holds the list of vertices in clipped polygon
  121.     int xmin,xmax;    // minimum and maximum x-coordinates of clipped polygon
  122.     int ymin,ymax;    // minimum and maximum y-coordinates of clipped polygon
  123.     int zmin,zmax;    // minimum and maximum z-coordinates of clipped polygon
  124. } ClippedPolygonTYPE;
  125.  
  126.  
  127. // structure for complete vector object
  128. typedef struct
  129. {
  130.     int NumOfVertices;    // how many vertices in entire object
  131.     int NumOfPolygons;    // how many polygons in entire object
  132.     PolygonTYPE * Polygon;    // list of polygons in object
  133.     VertexTYPE * Vertex;    // list of vertices
  134. } ObjectTYPE;
  135.  
  136.  
  137. // structure for polygon list
  138. typedef struct
  139. {
  140.     int NumOfPolygons;    // number of polygons in polygon list
  141.     PolygonTYPE Polygon[100];    // list of polygons
  142. } PolygonListTYPE;
  143.  
  144.  
  145.  
  146. // structure for light source for use in shading
  147. typedef struct
  148. {
  149.     Fixedpoint x;
  150.     Fixedpoint y;
  151.     Fixedpoint z;
  152. } LightSourceTYPE;
  153.  
  154. // structure for erasing box
  155. typedef struct
  156. {
  157.     int top;
  158.     int bottom;
  159.     int left;
  160.     int right;
  161. } EraseBoxTYPE;
  162.  
  163.  
  164. //----------------------------------------------------------------------
  165.  
  166.  
  167. // origional polygon vector object
  168. ObjectTYPE Object;
  169.  
  170. // polygon list
  171. PolygonListTYPE PolygonList;
  172.  
  173. // clipped polygon array
  174. ClippedPolygonTYPE ClipArray;
  175.  
  176. // light source
  177. LightSourceTYPE LightSource;
  178.  
  179. // Erasing box
  180. EraseBoxTYPE EraseBoxNew,EraseBoxOld,EraseBoxVeryOld;
  181.  
  182. //---------------------------------------------------------------
  183.  
  184.  
  185. void Create_lookup_tables(void)
  186. {
  187.     int i;
  188.     for(i=0; i<MaxDegrees; i++)
  189.     {
  190.         cosine[i]=Float2Fixed(cos((float)i*360/MaxDegrees * 3.14159265 / 180.0));
  191.         sine[i]  =Float2Fixed(sin((float)i*360/MaxDegrees * 3.14159265 / 180.0));
  192.     }
  193. }
  194.  
  195.  
  196. //---------------------------------------------------------------
  197.  
  198.  
  199. // function prototypes
  200. void Rotate_vector_object(void);
  201. void Create_lookup_tables(void);
  202. int main(int argc,char *argv[]);
  203. int LoadObject(char *);
  204. int getnumber(FILE *f);
  205. char nextchar(FILE *f);
  206. void RotateOnX(void);
  207. void RotateOnY(void);
  208. void RotateOnZ(void);
  209. void RotateOnAll(void);
  210. void SelectDistance(void);
  211. void MakePolygonList(void);
  212. int Backface(PolygonTYPE p);
  213. void ZSort();
  214. void ShowObject(void);
  215. void DrawPolygonList(void);
  216. void DrawDebugDots(void);
  217. void CalculateColor(void);
  218. void CalculateNormals(void);
  219. void Rotate_Normals(void);
  220. void SetupLightSourceManually(void);
  221. void SetupLightSourceDefault(void);
  222. void InitializeEraseBox(void);
  223. void ZClip(PolygonTYPE *polygon, ClippedPolygonTYPE *clip);
  224. void XYClip(ClippedPolygonTYPE *clip);
  225. void WaitVerticalRetrace(void);
  226. void FadeInPalette(unsigned char *,int);
  227. void FadeOutPalette(int);
  228. void GetPalette(unsigned char *);
  229. void SetPalette(unsigned char *);
  230. void FadeInOne64th(unsigned char *,unsigned char *);
  231. void FadeOutOne64th(unsigned char *);
  232.  
  233.  
  234.  
  235. //--------------------------------------------------------------------
  236.  
  237.  
  238. void RotateOnAll(void)
  239. {
  240.     xangle=0;
  241.     yangle=0;
  242.     zangle=0;
  243.  
  244.     SetPalette(currentpalette);
  245.     x_set_mode(X_MODE_320x240,320);
  246.     x_set_doublebuffer(240);
  247.     FadeInPalette(vedpalette,1);
  248.  
  249.     // rotate around all three axis 3 times
  250.     do
  251.     {
  252.         if((xangle+=3) >= MaxDegrees)
  253.             xangle=0;
  254.         if((yangle+=2) >= MaxDegrees)
  255.             yangle=0;
  256.         if((zangle+=3) >= MaxDegrees)
  257.             zangle=0;
  258.         ShowObject();
  259.         x_page_flip(0,0);
  260.         if(kbhit())
  261.             break;
  262.     } while(!kbhit());
  263.     getch();
  264.     FadeOutPalette(1);
  265.     x_text_mode();
  266. }
  267.  
  268.  
  269. //-----------------------------------------------------------------------
  270.  
  271.  
  272. void RotateOnX(void)
  273. {
  274.     xangle=270;
  275.     yangle=180;
  276.     zangle=180;
  277.  
  278.     SetPalette(currentpalette);
  279.     x_set_mode(X_MODE_320x240,320);
  280.     x_set_doublebuffer(240);
  281.     FadeInPalette(vedpalette,1);
  282.  
  283.     // rotate around all three axis 3 times
  284.     do
  285.     {
  286.         if((xangle+=1) >= MaxDegrees)
  287.             xangle=0;
  288.         ShowObject();
  289.         x_page_flip(0,0);
  290.         if(kbhit())
  291.             break;
  292.     } while(!kbhit());
  293.     getch();
  294.     FadeOutPalette(1);
  295.     x_text_mode();
  296. }
  297.  
  298.  
  299. //-----------------------------------------------------------------------
  300.  
  301.  
  302. void RotateOnY(void)
  303. {
  304.     xangle=90;
  305.     yangle=0;
  306.     zangle=0;
  307.  
  308.     SetPalette(currentpalette);
  309.     x_set_mode(X_MODE_320x240,320);
  310.     x_set_doublebuffer(240);
  311.     FadeInPalette(vedpalette,1);
  312.  
  313.     // rotate around all three axis 3 times
  314.     do
  315.     {
  316.         if((yangle+=1) >= MaxDegrees)
  317.             yangle=0;
  318.         ShowObject();
  319.         x_page_flip(0,0);
  320.         if(kbhit())
  321.             break;
  322.     } while(!kbhit());
  323.     getch();
  324.     FadeOutPalette(1);
  325.     x_text_mode();
  326. }
  327.  
  328.  
  329. //-----------------------------------------------------------------------
  330.  
  331.  
  332. void RotateOnZ(void)
  333. {
  334.     xangle=270;
  335.     yangle=180;
  336.     zangle=180;
  337.  
  338.     SetPalette(currentpalette);
  339.     x_set_mode(X_MODE_320x240,320);
  340.     x_set_doublebuffer(240);
  341.     FadeInPalette(vedpalette,1);
  342.  
  343.     // rotate around all three axis 3 times
  344.     do
  345.     {
  346.         if((zangle+=1) >= MaxDegrees)
  347.             zangle=0;
  348.         ShowObject();
  349.         x_page_flip(0,0);
  350.         if(kbhit())
  351.             break;
  352.     } while(!kbhit());
  353.     getch();
  354.     FadeOutPalette(1);
  355.     x_text_mode();
  356. }
  357.  
  358.  
  359. //----------------------------------------------------------------------
  360.  
  361.  
  362. void SelectDistance(void)
  363. {
  364.     SetPalette(currentpalette);
  365.     x_text_mode();
  366.     FadeInPalette(vedpalette,1);
  367.     printf("Please enter the distance away from the screen : ");
  368.     scanf("%li",&distance);
  369.     FadeOutPalette(1);
  370.     x_text_mode();
  371. }
  372.  
  373.  
  374. //----------------------------------------------------------------------
  375.  
  376.  
  377. void Rotate_vector_object(void)
  378. {
  379.     int i;
  380.     long tempx,tempy,tempz;
  381.  
  382.     Fixedpoint nx,ny,nz,cosxangle,sinxangle,cosyangle,sinyangle,coszangle,sinzangle;
  383.  
  384.     // get the sine and cosine angles to save time from table lookup
  385.     sinxangle=sine[xangle];
  386.     cosxangle=cosine[xangle];
  387.     sinyangle=sine[yangle];
  388.     cosyangle=cosine[yangle];
  389.     sinzangle=sine[zangle];
  390.     coszangle=cosine[zangle];
  391.  
  392.     // first we have to do all the rotations
  393.     for(i=0;i<Object.NumOfVertices;i++)
  394.     {
  395.         // rotate around the x-axis
  396.         Object.Vertex[i].wz=FixedMul(Object.Vertex[i].oy,cosxangle) - FixedMul(Object.Vertex[i].oz,sinxangle);
  397.         Object.Vertex[i].wy=FixedMul(Object.Vertex[i].oy,sinxangle) + FixedMul(Object.Vertex[i].oz,cosxangle);
  398.         Object.Vertex[i].wx=Object.Vertex[i].ox;
  399.  
  400.         // rotate around the y-axis
  401.         nx=FixedMul(-Object.Vertex[i].wx,cosyangle) + FixedMul(Object.Vertex[i].wz,sinyangle);
  402.         nz=FixedMul(Object.Vertex[i].wx,sinyangle) + FixedMul(Object.Vertex[i].wz,cosyangle);
  403.         Object.Vertex[i].wx=nx;
  404.         Object.Vertex[i].wz=nz;
  405.  
  406.         // rotate around the z-axis
  407.         nx=FixedMul(Object.Vertex[i].wx,coszangle) - FixedMul(Object.Vertex[i].wy,sinzangle);
  408.         ny=FixedMul(Object.Vertex[i].wx,sinzangle) + FixedMul(Object.Vertex[i].wy,coszangle);
  409.         Object.Vertex[i].wx=nx;
  410.         Object.Vertex[i].wy=ny;
  411.  
  412.  
  413.         // project the 3-D coordinates to screen coordinates
  414.         Object.Vertex[i].sx=Fixed2Int(FixedMul(FixedDiv(Object.Vertex[i].wx,Object.Vertex[i].wz-Int2Fixed(distance)),Int2Fixed(256))) + (long)160;
  415.         Object.Vertex[i].sy=Fixed2Int(FixedMul(FixedDiv(Object.Vertex[i].wy,Object.Vertex[i].wz-Int2Fixed(distance)),Int2Fixed(256))) + (long)120;
  416.         Object.Vertex[i].sz=Fixed2Int(Object.Vertex[i].wz-Int2Fixed(distance));
  417.     }
  418. }
  419.  
  420.  
  421. //---------------------------------------------------------------
  422.  
  423.  
  424. int main(int argc,char *argv[])
  425. {
  426.     if(argc<=1)
  427.     {
  428.         printf("┌─────────────┐\n");
  429.         printf("│VED v0.4 beta│\n");
  430.         printf("└─────────────┘\n");
  431.         printf("syntax: VED04B filename.V04\n\n");
  432.         exit(1);
  433.     }
  434.  
  435.     if(LoadObject(argv[1])!=0)
  436.     {
  437.         printf("Could not find that file. Check to see if you gave the correct filename.\n");
  438.         exit(1);
  439.     }
  440.  
  441.     char menu_option;
  442.     int time_to_quit=0;
  443.  
  444.     // initialize very old erase box
  445.     EraseBoxVeryOld.top=WINDOW_TOP;
  446.     EraseBoxVeryOld.bottom=WINDOW_BOTTOM;
  447.     EraseBoxVeryOld.left=WINDOW_LEFT;
  448.     EraseBoxVeryOld.right=WINDOW_RIGHT;
  449.  
  450.     // initialize old erase box
  451.     EraseBoxOld.top=WINDOW_TOP;
  452.     EraseBoxOld.bottom=WINDOW_BOTTOM;
  453.     EraseBoxOld.left=WINDOW_LEFT;
  454.     EraseBoxOld.right=WINDOW_RIGHT;
  455.  
  456.     Create_lookup_tables();
  457.     CalculateNormals();
  458.     SetupLightSourceDefault();
  459.     InitializeEraseBox();
  460.     x_text_init();
  461.  
  462.     GetPalette(oldpalette);
  463.     FadeOutPalette(1);
  464.     x_text_mode();
  465.  
  466.     do    // display the main menu
  467.     {
  468.         SetPalette(currentpalette);
  469.         printf("                                  ┌─────────────┐\n");
  470.         printf("                                  │VED v0.4 beta│\n");
  471.         printf("                                  └─────────────┘\n\n");
  472.         printf("                        coded by Tumblin / Bodies In Motion\n\n\n");
  473.         printf("                        Distance = %i\n",distance);
  474.         printf("                        Light source = (%f,%f,%f)\n\n",Fixed2Float(LightSource.x),Fixed2Float(LightSource.y),Fixed2Float(LightSource.z));
  475.         printf("                      ┌───────────── MAIN MENU ────────────┐\n");
  476.         printf("                      │ [X] Rotate object on X-axis        │\n");
  477.         printf("                      │ [Y] Rotate object on Y-axis        │\n");
  478.         printf("                      │ [Z] Rotate object on Z-axis        │\n");
  479.         printf("                      │ [A] Rotate object on all three axis│\n");
  480.         printf("                      │ [D] Select distance from viewer    │\n");
  481.         printf("                      │ [L] Select new light source        │\n");
  482.         printf("                      │ [Q] Quit                           │\n");
  483.         printf("                      └────────────────────────────────────┘\n");
  484.         printf("                        Make your selection : ");
  485.         FadeInPalette(vedpalette,1);
  486.         menu_option=getche();
  487.  
  488.         // reset the number of frames shown
  489.         NumOfFrames=0;
  490.  
  491.         // evaluate user's selection
  492.         if(menu_option=='x' || menu_option=='X')
  493.             RotateOnX();
  494.         if(menu_option=='y' || menu_option=='Y')
  495.             RotateOnY();
  496.         if(menu_option=='z' || menu_option=='Z')
  497.             RotateOnZ();
  498.         if(menu_option=='a' || menu_option=='A')
  499.             RotateOnAll();
  500.         if(menu_option=='d' || menu_option=='D')
  501.             SelectDistance();
  502.         if(menu_option=='q' || menu_option=='Q')
  503.             time_to_quit=1;
  504.         if(menu_option=='l' || menu_option=='L')
  505.             SetupLightSourceManually();
  506.  
  507.     } while(time_to_quit != 1);
  508.  
  509.     free(&Object);
  510.     free(&PolygonList);
  511.     FadeOutPalette(1);
  512.     x_text_mode();
  513.     printf("This has been a Bodies In Motion production.\n\n");
  514.     FadeInPalette(oldpalette,1);
  515.     return(0);
  516. }
  517.  
  518.  
  519. //--------------------------------------------------------------------------
  520.  
  521.  
  522. int LoadObject(char *filename)
  523. {
  524.     FILE *f;
  525.     int num,vertnum,polynum;
  526.  
  527.     ObjectTYPE *object=&Object;
  528.  
  529.     f=fopen(filename,"r");
  530.     if(f==NULL)
  531.     {
  532.         printf("Could not find that file. Check to see if you gave the correct filename.\n");
  533.         exit(1);
  534.     }
  535.     // first get the number of vertices in the object
  536.     object->NumOfVertices=getnumber(f);
  537.     // allocate memory for vertex array
  538.     object->Vertex=new VertexTYPE[object->NumOfVertices];
  539.     // load vertices into vertex array
  540.     for(vertnum=0; vertnum < object->NumOfVertices; vertnum++)
  541.     {
  542.         // assign pointer to current vertex
  543.         VertexTYPE *curvert=&object->Vertex[vertnum];
  544.         // get the original local coordinates
  545.         curvert->ox=Int2Fixed(getnumber(f));
  546.         curvert->wx=curvert->ox;
  547.         curvert->oy=Int2Fixed(getnumber(f));
  548.         curvert->wy=curvert->oy;
  549.         curvert->oz=Int2Fixed(getnumber(f));
  550.         curvert->wz=curvert->oz;
  551.     }
  552.     // get the number of polygons in the object
  553.     object->NumOfPolygons=getnumber(f);
  554.     // assign memory for polygon array
  555.     object->Polygon=new PolygonTYPE[object->NumOfPolygons];
  556.     // load polygons into polygon array
  557.     for(polynum=0; polynum < object->NumOfPolygons; polynum++)
  558.     {
  559.         // assign pointer to current polygon
  560.         PolygonTYPE *curpoly=&object->Polygon[polynum];
  561.         // get number of vertices in current polygon
  562.         curpoly->NumOfVertices=getnumber(f);
  563.         // assign memory for vertex array
  564.         curpoly->Vertex=new VertexTYPE *[curpoly->NumOfVertices];
  565.         // create array of pointers to vertices
  566.         for(vertnum=0;vertnum<curpoly->NumOfVertices;vertnum++)
  567.         {
  568.             // allocate memory for pointer and point it at vertex in vertex array
  569.             curpoly->Vertex[vertnum]=&object->Vertex[getnumber(f)];
  570.         }
  571.         // get color of current polygon
  572.         curpoly->ShadingColor=getnumber(f);
  573.     }
  574.     fclose(f);
  575.     return(0);
  576. }
  577.  
  578. int getnumber(FILE *f)
  579. {
  580.     int num;
  581.     char ch;
  582.     int sign=1;
  583.  
  584.     num=0;
  585.     if((ch=nextchar(f))=='-')
  586.     {
  587.          sign=-1;
  588.          ch=nextchar(f);
  589.     }
  590.     while(isdigit(ch))
  591.     {
  592.         num=num*10+ch-'0';
  593.         ch=nextchar(f);
  594.     }
  595.     return(num*sign);
  596. }
  597.  
  598. char nextchar(FILE *f)
  599. {
  600.     char ch;
  601.  
  602.     while(!feof(f))
  603.     {
  604.         while(isspace(ch=fgetc(f)));
  605.             if (ch=='*')
  606.                 while((ch=fgetc(f))!='\n');
  607.                     else return(ch);
  608.     }
  609.     return(0);
  610. }
  611.  
  612.  
  613. //--------------------------------------------------------------------------
  614.  
  615.  
  616. void MakePolygonList(void)
  617. {
  618.     // create a list of all polygons potentially visible on the display,
  619.     // removing backfaces and determine the minimum and maximum z coordinates
  620.  
  621.     int count=0;    // determine # of polygons in list
  622.  
  623.     // loop through all polygons in object
  624.     for(int polynum=0; polynum < Object.NumOfPolygons; polynum++)
  625.     {
  626.         // create a pointer to current polygon
  627.         PolygonTYPE *polyptr=&Object.Polygon[polynum];
  628.  
  629.         // if polygon isn't a backface, consider it for list
  630.         if(!Backface(*polyptr))
  631.         {
  632.             int pzmax=-32767;    // initialize min and max to
  633.             int pzmin=32767;    // highest & lowest possible values
  634.             int pxmax=-32767;    // initialize min and max to
  635.             int pxmin=32767;    // highest & lowest possible values
  636.             int pymax=-32767;    // initialize min and max to
  637.             int pymin=32767;    // highest & lowest possible values
  638.  
  639.             // loop through all vertices in polygon to find ones with higher
  640.             // and lower coordinates than current min & max
  641.             for(int v=0; v < polyptr->NumOfVertices; v++)
  642.             {
  643.                 // do the z-axis
  644.                 if(polyptr->Vertex[v]->sz > pzmax)
  645.                 {
  646.                     pzmax=polyptr->Vertex[v]->sz;
  647.                 }
  648.                 if(polyptr->Vertex[v]->sz < pzmin)
  649.                 {
  650.                     pzmin=polyptr->Vertex[v]->sz;
  651.                 }
  652.  
  653.                 // do the x-axis
  654.                 if(polyptr->Vertex[v]->sx > pxmax)
  655.                 {
  656.                     pxmax=polyptr->Vertex[v]->sx;
  657.                 }
  658.                 if(polyptr->Vertex[v]->sx < pxmin)
  659.                 {
  660.                     pxmin=polyptr->Vertex[v]->sx;
  661.                 }
  662.  
  663.                 // do the y-axis
  664.                 if(polyptr->Vertex[v]->sy > pymax)
  665.                 {
  666.                     pymax=polyptr->Vertex[v]->sy;
  667.                 }
  668.                 if(polyptr->Vertex[v]->sy < pymin)
  669.                 {
  670.                     pymin=polyptr->Vertex[v]->sy;
  671.                 }
  672.             }
  673.  
  674.             // put min and max in polygon descriptor
  675.             polyptr->zmin=pzmin;
  676.             polyptr->zmax=pzmax;
  677.             polyptr->xmin=pxmin;
  678.             polyptr->xmax=pxmax;
  679.             polyptr->ymin=pymin;
  680.             polyptr->ymax=pymax;
  681.  
  682.             // calculate center of polygon
  683.             polyptr->zcenter=(pzmax+pzmin)>>1;
  684.             polyptr->xcenter=(pxmax+pxmin)>>1;
  685.             polyptr->ycenter=(pymax+pymin)>>1;
  686.  
  687.             // if polygon is in front of view plane, add it to the list
  688.             if(pzmax < 0)
  689.             {
  690.                 PolygonList.Polygon[count++]=*polyptr;
  691.             }
  692.         }
  693.     }
  694.     PolygonList.NumOfPolygons=count;
  695. }
  696.  
  697.  
  698. //-------------------------------------------------------------------------
  699.  
  700.  
  701. int Backface(PolygonTYPE p)
  702. {
  703.     // returns 0 if polygon is visible, -1 if not
  704.     // the polygon must be part of a convex polyhedron
  705.  
  706.     VertexTYPE *v0,*v1,*v2;    // pointers to three vertices
  707.  
  708.     // point to vertices
  709.     v0=p.Vertex[0];
  710.     v1=p.Vertex[1];
  711.     v2=p.Vertex[2];
  712.  
  713.     int z= (v1->sx - v0->sx) * (v2->sy - v0->sy)
  714.                 -(v1->sy - v0->sy) * (v2->sx - v0->sx);
  715.  
  716.     return(z<0);
  717. }
  718.  
  719.  
  720. //--------------------------------------------------------------------------
  721.  
  722.  
  723. void ZSort(void)
  724. {
  725.     // sort the polygon list into reverse order by z coordinates
  726.  
  727.     int swapflag=-1;    // force initial pass through list
  728.     while(swapflag)    // loop until no swaps performed
  729.     {
  730.         swapflag=0;
  731.  
  732.         // loop through polygon list
  733.         for(int i=0; i < (PolygonList.NumOfPolygons-1);i++)
  734.         {
  735.             // are polygons in order?
  736.             if(PolygonList.Polygon[i].zcenter > PolygonList.Polygon[i+1].zcenter)
  737.             {
  738.                 // if so, swap them
  739.                 PolygonTYPE temp=PolygonList.Polygon[i];
  740.                 PolygonList.Polygon[i]=PolygonList.Polygon[i+1];
  741.                 PolygonList.Polygon[i+1]=temp;
  742.                 swapflag=-1;    // indicate that swap was performed
  743.             }
  744.         }
  745.     }
  746. }
  747.  
  748.  
  749. //-------------------------------------------------------------------------
  750.  
  751.  
  752. void DrawPolygonList()
  753. {
  754.     int i,j;
  755.  
  756.     // erase the previous frame
  757.     x_rect_fill(EraseBoxVeryOld.left,EraseBoxVeryOld.top,EraseBoxVeryOld.right+1,EraseBoxVeryOld.bottom+1,HiddenPageOffs,0);
  758.  
  759.     // loop through polygon list and draw each polygon
  760.     for(i=0; i<PolygonList.NumOfPolygons;i++)
  761.     {
  762.         ZClip(&PolygonList.Polygon[i],&ClipArray);
  763.         if(ClipArray.NumOfVertices > 0)
  764.         {
  765.             // clip against sides of viewport
  766.             XYClip(&ClipArray);
  767.             // check to make sure polygon wan't clipped out of existence
  768.             if(ClipArray.NumOfVertices > 0)
  769.             {
  770.                 // draw polygon
  771.  
  772.                 // loop through all vertices in polygon and draw triangular pieces
  773.                 for(j=0; j < ClipArray.NumOfVertices-2;j++)
  774.                 {
  775.                     x_triangle(ClipArray.Vertex[0].x,
  776.                                          ClipArray.Vertex[0].y,
  777.                                          ClipArray.Vertex[j+1].x,
  778.                                          ClipArray.Vertex[j+1].y,
  779.                                          ClipArray.Vertex[j+2].x,
  780.                                          ClipArray.Vertex[j+2].y,
  781.                                          ClipArray.Color,
  782.                                          HiddenPageOffs);
  783.                 }
  784.             }
  785.         }
  786.     }
  787.  
  788.     InitializeEraseBox();
  789.  
  790.     // figure out the bounding box for erasing the object next frame
  791.     for(i=0; i<Object.NumOfVertices; i++)
  792.     {
  793.         if(Object.Vertex[i].sy < EraseBoxNew.top)
  794.             EraseBoxNew.top=Object.Vertex[i].sy;
  795.         if(Object.Vertex[i].sy > EraseBoxNew.bottom)
  796.             EraseBoxNew.bottom=Object.Vertex[i].sy;
  797.         if(Object.Vertex[i].sx < EraseBoxNew.left)
  798.             EraseBoxNew.left=Object.Vertex[i].sx;
  799.         if(Object.Vertex[i].sx > EraseBoxNew.right)
  800.             EraseBoxNew.right=Object.Vertex[i].sx;
  801.     }
  802.  
  803.     // increase the right & bottom of the bounding box by one pixel
  804.     // (something with the XLIB code that I don't understand :-)
  805.     EraseBoxNew.right++;
  806.     EraseBoxNew.bottom++;
  807.  
  808.     // clip the bounding box to screen limits
  809.     if(EraseBoxNew.top < WINDOW_TOP)
  810.         EraseBoxNew.top=WINDOW_TOP;
  811.     if(EraseBoxNew.bottom > WINDOW_BOTTOM)
  812.         EraseBoxNew.bottom=WINDOW_BOTTOM;
  813.     if(EraseBoxNew.left < WINDOW_LEFT)
  814.         EraseBoxNew.left=WINDOW_LEFT;
  815.     if(EraseBoxNew.right > WINDOW_RIGHT)
  816.         EraseBoxNew.right=WINDOW_RIGHT;
  817.  
  818.     // make the very old bounding box = the old bounding box
  819.     EraseBoxVeryOld.top=EraseBoxOld.top;
  820.     EraseBoxVeryOld.bottom=EraseBoxOld.bottom;
  821.     EraseBoxVeryOld.left=EraseBoxOld.left;
  822.     EraseBoxVeryOld.right=EraseBoxOld.right;
  823.  
  824.     // make the old bounding box = the new bounding box
  825.     EraseBoxOld.top=EraseBoxNew.top;
  826.     EraseBoxOld.bottom=EraseBoxNew.bottom;
  827.     EraseBoxOld.left=EraseBoxNew.left;
  828.     EraseBoxOld.right=EraseBoxNew.right;
  829.  
  830. }
  831.  
  832.  
  833. //--------------------------------------------------------------
  834.  
  835.  
  836. void DrawDebugDots(void)
  837. {
  838.     int i,j;
  839.  
  840.     // loop through all vertices in object
  841.     for(i=0;i < Object.NumOfVertices; i++)
  842.     {
  843.         x_put_pix(Object.Vertex[i].sx,Object.Vertex[i].sy,HiddenPageOffs,15);
  844.         x_printf(Object.Vertex[i].sx,Object.Vertex[i].sy,HiddenPageOffs,4,"%i",i);
  845.     }
  846. }
  847.  
  848. //--------------------------------------------------------------------------
  849.  
  850.  
  851. void CalculateNormals(void)
  852. {
  853.     double x1,x2,x3,y1,y2,y3,z1,z2,z3,xlen,ylen,zlen,length;
  854.  
  855.     for(int i=0;i < Object.NumOfPolygons; i++)
  856.     {
  857.         x1=Fixed2Float(Object.Polygon[i].Vertex[0]->ox);
  858.         x2=Fixed2Float(Object.Polygon[i].Vertex[1]->ox);
  859.         x3=Fixed2Float(Object.Polygon[i].Vertex[2]->ox);
  860.         y1=Fixed2Float(Object.Polygon[i].Vertex[0]->oy);
  861.         y2=Fixed2Float(Object.Polygon[i].Vertex[1]->oy);
  862.         y3=Fixed2Float(Object.Polygon[i].Vertex[2]->oy);
  863.         z1=Fixed2Float(Object.Polygon[i].Vertex[0]->oz);
  864.         z2=Fixed2Float(Object.Polygon[i].Vertex[1]->oz);
  865.         z3=Fixed2Float(Object.Polygon[i].Vertex[2]->oz);
  866.  
  867.         // calculate perpendicular via the cross product of 1st vertex & normal
  868.         xlen = Object.Polygon[i].Normalox = (y1-y2)*(z1-z3) - (z1-z2)*(y1-y3);
  869.         ylen = Object.Polygon[i].Normaloy = (z1-z2)*(x1-x3) - (x1-x2)*(z1-z3);
  870.         zlen = Object.Polygon[i].Normaloz = (x1-x2)*(y1-y3) - (y1-y2)*(x1-x3);
  871.  
  872.         // calculate the length of the normal
  873.         length = sqrt(xlen*xlen + ylen*ylen + zlen*zlen);
  874.  
  875.         // scale it to a unit normal
  876.         Object.Polygon[i].Normalox = Float2Fixed(xlen / length);
  877.         Object.Polygon[i].Normaloy = Float2Fixed(ylen / length);
  878.         Object.Polygon[i].Normaloz = Float2Fixed(zlen / length);
  879.     }
  880. }
  881.  
  882.  
  883. //--------------------------------------------------------------------------
  884.  
  885.  
  886. void CalculateColor(void)
  887. {
  888.     int color;
  889.  
  890.     for(int i=0; i < Object.NumOfPolygons; i++)
  891.     {
  892.         dotproduct=FixedMul(Object.Polygon[i].Normalwx , LightSource.x) +
  893.                              FixedMul(Object.Polygon[i].Normalwy , LightSource.y) +
  894.                              FixedMul(Object.Polygon[i].Normalwz , LightSource.z);
  895.  
  896.         Object.Polygon[i].Color=Fixed2Int(FixedMul(dotproduct,Int2Fixed(16))) + Object.Polygon[i].ShadingColor*32;
  897.  
  898.         if(dotproduct>=Int2Fixed(0))
  899.             Object.Polygon[i].Color=Fixed2Int(FixedMul(dotproduct,Int2Fixed(16))) + Object.Polygon[i].ShadingColor*32;
  900.  
  901.     }
  902. }
  903.  
  904.  
  905. //----------------------------------------------------------------------
  906.  
  907.  
  908. void Rotate_Normals(void)
  909. {
  910.     int i;
  911.     Fixedpoint nx,ny,nz,cosxangle,sinxangle,cosyangle,sinyangle,coszangle,sinzangle;
  912.  
  913.     // get the sine and cosine angles to save time from table lookup
  914.     sinxangle=sine[xangle];
  915.     cosxangle=cosine[xangle];
  916.     sinyangle=sine[yangle];
  917.     cosyangle=cosine[yangle];
  918.     sinzangle=sine[zangle];
  919.     coszangle=cosine[zangle];
  920.  
  921.     for(i=0;i<Object.NumOfPolygons;i++)
  922.     {
  923.         // rotate around the x-axis
  924.         nz=FixedMul(Object.Polygon[i].Normaloy , cosxangle) - FixedMul(Object.Polygon[i].Normaloz , sinxangle);
  925.         ny=FixedMul(Object.Polygon[i].Normaloy , sinxangle) + FixedMul(Object.Polygon[i].Normaloz , cosxangle);
  926.         Object.Polygon[i].Normalwx=Object.Polygon[i].Normalox;;
  927.         Object.Polygon[i].Normalwy=ny;
  928.         Object.Polygon[i].Normalwz=nz;
  929.  
  930.         // rotate around the y-axis
  931.         nx=FixedMul(-Object.Polygon[i].Normalwx , cosyangle) + FixedMul(Object.Polygon[i].Normalwz , sinyangle);
  932.         nz=FixedMul(Object.Polygon[i].Normalwx , sinyangle) + FixedMul(Object.Polygon[i].Normalwz , cosyangle);
  933.         Object.Polygon[i].Normalwx=nx;
  934.         Object.Polygon[i].Normalwz=nz;
  935.  
  936.         // rotate around the z-axis
  937.         nx=FixedMul(Object.Polygon[i].Normalwx , coszangle) - FixedMul(Object.Polygon[i].Normalwy , sinzangle);
  938.         ny=FixedMul(Object.Polygon[i].Normalwx , sinzangle) + FixedMul(Object.Polygon[i].Normalwy , coszangle);
  939.         Object.Polygon[i].Normalwx=-nx;
  940.         Object.Polygon[i].Normalwy=-ny;
  941.         Object.Polygon[i].Normalwz=-nz;
  942.     }
  943. }
  944.  
  945.  
  946. //--------------------------------------------------------------------------
  947.  
  948.  
  949. void SetupLightSourceManually(void)
  950. {
  951.     double xlen,ylen,zlen,length;
  952.  
  953.     x_text_mode();
  954.     SetPalette(currentpalette);
  955.     printf("Setting Light Source for shading\n");
  956.     printf("Please enter values in the range of (+/-) 10, but not 0\n");
  957.     printf("( the default is  10,10,10 ).\n\n");
  958.     printf("Enter the light source's X coordinate : ");
  959.     FadeInPalette(vedpalette,1);
  960.     scanf("%lf",&xlen);
  961.     printf("Enter the light source's Y coordinate : ");
  962.     scanf("%lf",&ylen);
  963.     printf("Enter the light source's Z coordinate : ");
  964.     scanf("%lf",&zlen);
  965.  
  966.     // calculate the length of the vector (light source to 0,0,0)
  967.     length = sqrt(xlen*xlen + ylen*ylen + zlen*zlen);
  968.  
  969.     // scale it to a unit vector
  970.     LightSource.x = Float2Fixed(-xlen/length);
  971.     LightSource.y = Float2Fixed(ylen/length);
  972.     LightSource.z = Float2Fixed(zlen/length);
  973.     FadeOutPalette(1);
  974.     x_text_mode();
  975. }
  976.  
  977.  
  978. //--------------------------------------------------------------------------
  979.  
  980.  
  981. void SetupLightSourceDefault(void)
  982. {
  983.     double xlen,ylen,zlen,length;
  984.  
  985.     // assign the delault light source position
  986.     xlen=10;
  987.     ylen=10;
  988.     zlen=10;
  989.  
  990.     // calculate the length of the vector (light source to 0,0,0)
  991.     length = sqrt(xlen*xlen + ylen*ylen + zlen*zlen);
  992.  
  993.     // scale it to a unit vector
  994.     LightSource.x = Float2Fixed(-xlen/length);
  995.     LightSource.y = Float2Fixed(ylen/length);
  996.     LightSource.z = Float2Fixed(zlen/length);
  997. }
  998.  
  999.  
  1000. //--------------------------------------------------------------------------
  1001.  
  1002.  
  1003. void InitializeEraseBox(void)
  1004. {
  1005.     // make the boundaries artificially extreme
  1006.     EraseBoxNew.top=WINDOW_BOTTOM;
  1007.     EraseBoxNew.bottom=WINDOW_TOP;
  1008.     EraseBoxNew.left=WINDOW_RIGHT;
  1009.     EraseBoxNew.right=WINDOW_LEFT;
  1010. }
  1011.  
  1012.  
  1013. //--------------------------------------------------------------------------
  1014.  
  1015.  
  1016. void ZClip(PolygonTYPE *polygon, ClippedPolygonTYPE *clip)
  1017. {
  1018.     // clip the polygon to the edges of the 3-d display area
  1019.  
  1020.     // create a pointer to the vertices of the clipped polygon structure
  1021.     ClipTYPE * pcv=clip->Vertex;
  1022.  
  1023.     // get info from polygon structure and put it into clipped
  1024.     // polygon structure
  1025.     clip->Color = polygon->Color;
  1026.     clip->xmin = polygon->xmin;
  1027.     clip->xmax = polygon->xmax;
  1028.     clip->ymin = polygon->ymin;
  1029.     clip->ymax = polygon->ymax;
  1030.     clip->zmin = polygon->zmin;
  1031.     clip->zmax = polygon->zmax;
  1032.  
  1033.     // clip the polygon against the front of the view volume
  1034.     int cp = 0;    // point to current vertex of clipped polygon
  1035.     int zmin = -2;    // set minimum z coordinate
  1036.  
  1037.     // initialize pointer to last vertex
  1038.     int v1=polygon->NumOfVertices - 1;
  1039.  
  1040.     // loop through all edges of the polygon
  1041.     for(int v2=0; v2 < polygon->NumOfVertices; v2++)
  1042.     {
  1043.         VertexTYPE *pv1 = polygon->Vertex[v1];
  1044.         VertexTYPE *pv2 = polygon->Vertex[v2];
  1045.  
  1046.         // categorize the edges by type
  1047.         if((pv1->sz <= zmin) && (pv2->sz <= zmin))
  1048.         {
  1049.             // edge entirely inside front
  1050.             pcv[cp].x = pv2->sx;
  1051.             pcv[cp].y = pv2->sy;
  1052.             pcv[cp++].z = pv2->sz;
  1053.         }
  1054.  
  1055.         if((pv1->sz <= zmin) && (pv2->sz > zmin))
  1056.         {
  1057.             // edge leaving view volume
  1058.             float t = (float)(zmin - pv1->sz)/(float)(pv2->sz - pv1->sz);
  1059.             pcv[cp].x = pv1->sx + (pv2->sx - pv1->sx) * t;
  1060.             pcv[cp].y = pv1->sy + (pv2->sy - pv1->sy) * t;
  1061.             pcv[cp++].z=zmin;
  1062.         }
  1063.         if((pv1->sz > zmin) && (pv2->sz <= zmin))
  1064.         {
  1065.             // edge is entering view volume
  1066.             float t = (float)(zmin - pv1->sz)/(float)(pv2->sz - pv1->sz);
  1067.             pcv[cp].x = pv1->sx + (pv2->sx - pv1->sx) * t;
  1068.             pcv[cp].y = pv1->sy + (pv2->sy - pv1->sy) * t;
  1069.             pcv[cp++].z = zmin;
  1070.             pcv[cp].x = pv2->sx;
  1071.             pcv[cp].y = pv2->sy;
  1072.             pcv[cp++].z = pv2->sz;
  1073.         }
  1074.         v1=v2;    // advance to the next vertex
  1075.     }
  1076.     // update number of vertices in clipped polygon structure
  1077.     clip->NumOfVertices = cp;
  1078. }
  1079.  
  1080.  
  1081. //--------------------------------------------------------------------------
  1082.  
  1083.  
  1084. void XYClip(ClippedPolygonTYPE *clip)
  1085. {
  1086.     // clip polygon against sides of 3-d display area
  1087.  
  1088.     int temp;    // miscellaneous temporary storage
  1089.     ClipTYPE *pcv = clip->Vertex;
  1090.  
  1091.     /////////////////////////////////////////////
  1092.     // clip polygon against left edge of display
  1093.     int cp = 0;
  1094.  
  1095.     // initialize pointer to last vertex
  1096.  
  1097.     int v1=clip->NumOfVertices - 1;
  1098.     for(int v2=0; v2 < clip->NumOfVertices; v2++)
  1099.     {
  1100.         // categorize edges by type
  1101.         if((pcv[v1].x >= WINDOW_LEFT) && (pcv[v2].x >= WINDOW_LEFT))
  1102.         {
  1103.             // edge isn't off left side of display
  1104.             pcv[cp].x1 = pcv[v2].x;
  1105.             pcv[cp++].y1 = pcv[v2].y;
  1106.         }
  1107.  
  1108.         if((pcv[v1].x >= WINDOW_LEFT) && (pcv[v2].x < WINDOW_LEFT))
  1109.         {
  1110.             // edge is leaving display
  1111.             float m = (float)(pcv[v2].y - pcv[v1].y)/(float)(pcv[v2].x - pcv[v1].x);
  1112.             pcv[cp].x1 = WINDOW_LEFT;
  1113.             pcv[cp++].y1 = pcv[v1].y + m * (WINDOW_LEFT - pcv[v1].x);
  1114.         }
  1115.         if((pcv[v1].x < WINDOW_LEFT) && (pcv[v2].x >= WINDOW_LEFT))
  1116.         {
  1117.             // edge is entering display
  1118.             float m = (float)(pcv[v2].y - pcv[v1].y)/(float)(pcv[v2].x - pcv[v1].x);
  1119.             pcv[cp].x1 = WINDOW_LEFT;
  1120.             pcv[cp++].y1 = pcv[v1].y + m * (WINDOW_LEFT - pcv[v1].x);
  1121.             pcv[cp].x1 = pcv[v2].x;
  1122.             pcv[cp++].y1 = pcv[v2].y;
  1123.         }
  1124.         v1=v2;
  1125.     }
  1126.     clip->NumOfVertices = cp;
  1127.  
  1128.     /////////////////////////////////////////////////////////
  1129.     // clip polygon against right edge of display
  1130.     cp = 0;
  1131.  
  1132.     // make pointer to last vertex
  1133.     v1=clip->NumOfVertices - 1;
  1134.     for(v2=0; v2 < clip->NumOfVertices; v2++)
  1135.     {
  1136.         // categorize edges by type
  1137.         if((pcv[v1].x1 <= WINDOW_RIGHT) && (pcv[v2].x1 <= WINDOW_RIGHT))
  1138.         {
  1139.             // edge isn't off right side of display
  1140.             pcv[cp].x = pcv[v2].x1;
  1141.             pcv[cp++].y = pcv[v2].y1;
  1142.         }
  1143.  
  1144.         if((pcv[v1].x1 <= WINDOW_RIGHT) && (pcv[v2].x1 > WINDOW_RIGHT))
  1145.         {
  1146.             // edge is leaving display
  1147.             float m = (float)(pcv[v2].y1 - pcv[v1].y1)/(float)(pcv[v2].x1 - pcv[v1].x1);
  1148.             pcv[cp].x = WINDOW_RIGHT;
  1149.             pcv[cp++].y = pcv[v1].y1 + m * (WINDOW_RIGHT - pcv[v1].x1);
  1150.         }
  1151.         if((pcv[v1].x1 > WINDOW_RIGHT) && (pcv[v2].x1 <= WINDOW_RIGHT))
  1152.         {
  1153.             // edge is entering display
  1154.             float m = (float)(pcv[v2].y1 - pcv[v1].y1)/(float)(pcv[v2].x1 - pcv[v1].x1);
  1155.             pcv[cp].x = WINDOW_RIGHT;
  1156.             pcv[cp++].y = pcv[v1].y1 + m * (WINDOW_RIGHT - pcv[v1].x1);
  1157.             pcv[cp].x = pcv[v2].x1;
  1158.             pcv[cp++].y = pcv[v2].y1;
  1159.         }
  1160.         v1 = v2;
  1161.     }
  1162.     clip->NumOfVertices = cp;
  1163.  
  1164.     ///////////////////////////////////////////////////////////////
  1165.     // clip polygon against upper edge of display
  1166.     cp = 0;
  1167.  
  1168.     // make pointer to last vertex
  1169.     v1 = clip->NumOfVertices - 1;
  1170.     for(v2=0; v2 < clip->NumOfVertices; v2++)
  1171.     {
  1172.         // categorize edges by type
  1173.         if((pcv[v1].y >= WINDOW_TOP) && (pcv[v2].y >= WINDOW_TOP))
  1174.         {
  1175.             // edge is not off top of display
  1176.             pcv[cp].x1 = pcv[v2].x;
  1177.             pcv[cp++].y1 = pcv[v2].y;
  1178.         }
  1179.  
  1180.         if((pcv[v1].y >= WINDOW_TOP) && (pcv[v2].y < WINDOW_TOP))
  1181.         {
  1182.             // edge is leaving display
  1183.             if((temp=pcv[v2].x - pcv[v1].x) != 0)
  1184.             {
  1185.                 float m = (float)(pcv[v2].y - pcv[v1].y)/(float)temp;
  1186.                 pcv[cp].x1 = pcv[v1].x + (WINDOW_TOP - pcv[v1].y) / m;
  1187.             }
  1188.             else
  1189.             {
  1190.                 pcv[cp].x1 = pcv[v1].x;
  1191.             }
  1192.             pcv[cp++].y1 = WINDOW_TOP;
  1193.         }
  1194.         if((pcv[v1].y < WINDOW_TOP) && (pcv[v2].y >= WINDOW_TOP))
  1195.         {
  1196.             // edge is entering display
  1197.             if((temp = pcv[v2].x - pcv[v1].x) != 0)
  1198.             {
  1199.                 float m = (float)(pcv[v2].y - pcv[v1].y)/(float)temp;
  1200.                 pcv[cp].x1 = pcv[v1].x + (WINDOW_TOP - pcv[v1].y) / m;
  1201.             }
  1202.             else
  1203.             {
  1204.                 pcv[cp].x1 = pcv[v1].x;
  1205.             }
  1206.             pcv[cp++].y1 = WINDOW_TOP;
  1207.             pcv[cp].x1 = pcv[v2].x;
  1208.             pcv[cp++].y1 = pcv[v2].y;
  1209.         }
  1210.         v1 = v2;
  1211.     }
  1212.     clip->NumOfVertices = cp;
  1213.  
  1214.     //////////////////////////////////////////////////////////////////
  1215.     // clip against lower edge of display
  1216.     cp = 0;
  1217.  
  1218.     // make a pointer to last vertex
  1219.     v1 = clip->NumOfVertices - 1;
  1220.     for(v2 = 0; v2 < clip->NumOfVertices; v2++)
  1221.     {
  1222.         // categorize edges by type
  1223.         if((pcv[v1].y1 <= WINDOW_BOTTOM) && (pcv[v2].y1 <= WINDOW_BOTTOM))
  1224.         {
  1225.             // edge is not off bottom of display
  1226.             pcv[cp].x = pcv[v2].x1;
  1227.             pcv[cp++].y = pcv[v2].y1;
  1228.         }
  1229.  
  1230.         if((pcv[v1].y1 <= WINDOW_BOTTOM) && (pcv[v2].y1 > WINDOW_BOTTOM))
  1231.         {
  1232.             // edge is leaving display
  1233.             if((temp=pcv[v2].x1 - pcv[v1].x1) != 0)
  1234.             {
  1235.                 float m = (float)(pcv[v2].y1 - pcv[v1].y1)/(float)temp;
  1236.                 pcv[cp].x = pcv[v1].x1 + (WINDOW_BOTTOM - pcv[v1].y1) / m;
  1237.             }
  1238.             else
  1239.             {
  1240.                 pcv[cp].x = pcv[v1].x1;
  1241.             }
  1242.             pcv[cp++].y = WINDOW_BOTTOM;
  1243.         }
  1244.         if((pcv[v1].y1 > WINDOW_BOTTOM) && (pcv[v2].y1 <= WINDOW_BOTTOM))
  1245.         {
  1246.             // edge is entering display
  1247.             if((temp=pcv[v2].x1 - pcv[v1].x1) != 0)
  1248.             {
  1249.                 float m = (float)(pcv[v2].y1 - pcv[v1].y1)/(float)temp;
  1250.                 pcv[cp].x = pcv[v1].x1 + (WINDOW_BOTTOM - pcv[v1].y1) / m;
  1251.             }
  1252.             else
  1253.             {
  1254.                 pcv[cp].x = pcv[v1].x1;
  1255.             }
  1256.             pcv[cp++].y = WINDOW_BOTTOM;
  1257.             pcv[cp].x = pcv[v2].x1;
  1258.             pcv[cp++].y = pcv[v2].y1;
  1259.         }
  1260.         v1 = v2;
  1261.     }
  1262.     clip->NumOfVertices = cp;
  1263. }
  1264.  
  1265.  
  1266. //--------------------------------------------------------------------------
  1267.  
  1268.  
  1269. void WaitVerticalRetrace(void)
  1270. {
  1271.     asm    mov dx,3dah
  1272.  
  1273.     top_of_retrace:
  1274.     asm    in    al,dx
  1275.     asm    and    al,08h
  1276.     asm    jnz    top_of_retrace
  1277.  
  1278.     bottom_of_retrace:
  1279.     asm    in    al,dx
  1280.     asm    and    al,08h
  1281.     asm    jz    bottom_of_retrace
  1282. }
  1283.  
  1284.  
  1285. //-----------------------------------------------------------------------
  1286.  
  1287.  
  1288. void GetPalette(unsigned char *palettebuffer)
  1289. {
  1290.     int i;
  1291.  
  1292.     for(i=0;i<256;i++)
  1293.     {
  1294.         outp(0x3c7,i);    // color number to get data from
  1295.         palettebuffer[i*3]   = inp(0x3c9);    // red
  1296.         palettebuffer[i*3+1] = inp(0x3c9);    // green
  1297.         palettebuffer[i*3+2] = inp(0x3c9);    // blue
  1298.     }
  1299. }
  1300.  
  1301.  
  1302. //-----------------------------------------------------------------------
  1303.  
  1304. void SetPalette(unsigned char *palettebuffer)
  1305. {
  1306.     int i;
  1307.  
  1308.     for(i=0;i<256;i++)
  1309.     {
  1310.         outp(0x3c8,i);    // color number to set
  1311.         outp(0x3c9,palettebuffer[i*3]);        // red
  1312.         outp(0x3c9,palettebuffer[i*3+1]);    // green
  1313.         outp(0x3c9,palettebuffer[i*3+2]);    // blue
  1314.     }
  1315. }
  1316.  
  1317.  
  1318. //-----------------------------------------------------------------------
  1319.  
  1320.  
  1321. void FadeInPalette(unsigned char *palettebuffer,int speed)
  1322. {
  1323.     int i,j,k;
  1324.     unsigned char temppalette[768]={0};
  1325.  
  1326.     for(i=0;i<64;i++)
  1327.     {
  1328.         for(j=0;j<256;j++)
  1329.         {
  1330.             // do the red component
  1331.             if(temppalette[j*3] < palettebuffer[j*3])
  1332.             {
  1333.                 temppalette[j*3]++;
  1334.             }
  1335.             // do the green component
  1336.             if(temppalette[j*3+1] < palettebuffer[j*3+1])
  1337.             {
  1338.                 temppalette[j*3+1]++;
  1339.             }
  1340.             // do the blue component
  1341.             if(temppalette[j*3+2] < palettebuffer[j*3+2])
  1342.             {
  1343.                 temppalette[j*3+2]++;
  1344.             }
  1345.         }
  1346.         for(k=0;k<speed;k++)
  1347.         {
  1348.             WaitVerticalRetrace();
  1349.         }
  1350.         SetPalette(temppalette);
  1351.     }
  1352. }
  1353.  
  1354.  
  1355. //-----------------------------------------------------------------------
  1356.  
  1357.  
  1358. void FadeOutPalette(int speed)
  1359. {
  1360.     int i,j,k;
  1361.     unsigned char temppalette[768];
  1362.  
  1363.     GetPalette(temppalette);
  1364.  
  1365.     for(i=0;i<64;i++)
  1366.     {
  1367.         for(j=0;j<256;j++)
  1368.         {
  1369.             // do the red component
  1370.             if(temppalette[j*3] > 0)
  1371.             {
  1372.                 temppalette[j*3]--;
  1373.             }
  1374.             // do the green component
  1375.             if(temppalette[j*3+1] > 0)
  1376.             {
  1377.                 temppalette[j*3+1]--;
  1378.             }
  1379.             // do the blue component
  1380.             if(temppalette[j*3+2] > 0)
  1381.             {
  1382.                 temppalette[j*3+2]--;
  1383.             }
  1384.         }
  1385.         for(k=0;k<speed;k++)
  1386.         {
  1387.             WaitVerticalRetrace();
  1388.         }
  1389.         SetPalette(temppalette);
  1390.     }
  1391. }
  1392.  
  1393.  
  1394. //-----------------------------------------------------------------------
  1395.  
  1396.  
  1397. void FadeInOne64th(unsigned char *srcpalette,unsigned char *curpalette)
  1398. {
  1399.     int i,j;
  1400.  
  1401.     for(j=0;j<256;j++)
  1402.     {
  1403.         // do the red component
  1404.         if(curpalette[j*3] < srcpalette[j*3])
  1405.         {
  1406.             curpalette[j*3]++;
  1407.         }
  1408.         // do the green component
  1409.         if(curpalette[j*3+1] < srcpalette[j*3+1])
  1410.         {
  1411.             curpalette[j*3+1]++;
  1412.         }
  1413.         // do the blue component
  1414.         if(curpalette[j*3+2] < srcpalette[j*3+2])
  1415.         {
  1416.             curpalette[j*3+2]++;
  1417.         }
  1418.     }
  1419.     SetPalette(curpalette);
  1420. }
  1421.  
  1422.  
  1423. //-----------------------------------------------------------------------
  1424.  
  1425.  
  1426. void FadeOutOne64th(unsigned char *curpalette)
  1427. {
  1428.     int i,j;
  1429.  
  1430.     for(j=0;j<256;j++)
  1431.     {
  1432.         // do the red component
  1433.         if(curpalette[j*3] > 0)
  1434.         {
  1435.             curpalette[j*3]--;
  1436.         }
  1437.         // do the green component
  1438.         if(curpalette[j*3+1] > 0)
  1439.         {
  1440.             curpalette[j*3+1]--;
  1441.         }
  1442.         // do the blue component
  1443.         if(curpalette[j*3+2] > 0)
  1444.         {
  1445.             curpalette[j*3+2]--;
  1446.         }
  1447.     }
  1448.     SetPalette(curpalette);
  1449. }
  1450.  
  1451.  
  1452. //-----------------------------------------------------------------------
  1453.  
  1454.  
  1455. void ShowObject(void)
  1456. {
  1457.     Rotate_vector_object();
  1458.     Rotate_Normals();
  1459.     CalculateColor();
  1460.     MakePolygonList();
  1461.     ZSort();
  1462.     if(debug_mode==1)
  1463.     {
  1464.         x_rect_fill(0,0,319,239,HiddenPageOffs,0);
  1465.     }
  1466.     DrawPolygonList();
  1467.  
  1468.     if(debug_mode==1)
  1469.     {
  1470.         DrawDebugDots();
  1471.         x_printf(0,0,HiddenPageOffs,4,"Number of frames = %u",NumOfFrames++);
  1472.         x_printf(0,10,HiddenPageOffs,4,"Number of polygons = %i",PolygonList.NumOfPolygons);
  1473.         //x_printf(0,20,HiddenPageOffs,4,"Color of polygon 0 = %i",Object.Polygon[0].Color);
  1474.         //x_printf(0,40,HiddenPageOffs,4,"Dot Product 0 = %f",dotproduct);
  1475.         //x_printf(0,50,HiddenPageOffs,4,"Normal x of polygon 0 = %f",Object.Polygon[0].Normalwx);
  1476.         //x_printf(0,60,HiddenPageOffs,4,"Normal y of polygon 0 = %f",Object.Polygon[0].Normalwy);
  1477.         //x_printf(0,70,HiddenPageOffs,4,"Normal z of polygon 0 = %f",Object.Polygon[0].Normalwz);
  1478.         //x_printf(0,80,HiddenPageOffs,4,"top = %i",EraseBoxOld.top);
  1479.         //x_printf(0,90,HiddenPageOffs,4,"bottom = %i",EraseBoxOld.bottom);
  1480.         //x_printf(0,100,HiddenPageOffs,4,"left = %i",EraseBoxOld.left);
  1481.         //x_printf(0,110,HiddenPageOffs,4,"right = %i",EraseBoxOld.right);
  1482.         for(int x=0;x<256;x++)
  1483.         {
  1484.             x_line(x,229,x,239,x,HiddenPageOffs);
  1485.         }
  1486.     }
  1487. }
  1488.